import { socket } from "./socket.js";
let list = [
  // 棋盘布局：type-种类，camp-阵营
  [
    { type: 1, camp: 1 },
    { type: 2, camp: 1 },
    { type: 3, camp: 1 },
    { type: 4, camp: 1 },
    { type: 5, camp: 1 },
    { type: 4, camp: 1 },
    { type: 3, camp: 1 },
    { type: 2, camp: 1 },
    { type: 1, camp: 1 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 6, camp: 1 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 6, camp: 1 },
    { type: 0 },
  ],
  [
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
  ],
  [
    { type: 0 },
    { type: 6, camp: 2 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 6, camp: 2 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 1, camp: 2 },
    { type: 2, camp: 2 },
    { type: 3, camp: 2 },
    { type: 4, camp: 2 },
    { type: 5, camp: 2 },
    { type: 4, camp: 2 },
    { type: 3, camp: 2 },
    { type: 2, camp: 2 },
    { type: 1, camp: 2 },
  ],
];

let overlist = [
  // 棋盘布局：type-种类，camp-阵营
  [
    { type: 1, camp: 1 },
    { type: 2, camp: 1 },
    { type: 3, camp: 1 },
    { type: 4, camp: 1 },
    { type: 5, camp: 1 },
    { type: 4, camp: 1 },
    { type: 3, camp: 1 },
    { type: 2, camp: 1 },
    { type: 1, camp: 1 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 6, camp: 1 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 6, camp: 1 },
    { type: 0 },
  ],
  [
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
    { type: 0 },
    { type: 7, camp: 1 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
    { type: 0 },
    { type: 7, camp: 2 },
  ],
  [
    { type: 0 },
    { type: 6, camp: 2 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 6, camp: 2 },
    { type: 0 },
  ],
  [
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
    { type: 0 },
  ],
  [
    { type: 1, camp: 2 },
    { type: 2, camp: 2 },
    { type: 3, camp: 2 },
    { type: 4, camp: 2 },
    { type: 5, camp: 2 },
    { type: 4, camp: 2 },
    { type: 3, camp: 2 },
    { type: 2, camp: 2 },
    { type: 1, camp: 2 },
  ],
];

let menu = {
  // 棋子属性 type
  // 棋子的枚举属性
  0: (y, x, type, tr) => {
    // 无棋子
    return new Qi(y, x, type, tr, 0);
  },
  1: (y, x, type, tr, camp) => {
    // 车
    return new Ju(y, x, type, tr, camp);
  },
  2: (y, x, type, tr, camp) => {
    // 马
    return new Ma(y, x, type, tr, camp);
  },
  3: (y, x, type, tr, camp) => {
    // 象
    return new Xiang(y, x, type, tr, camp);
  },
  4: (y, x, type, tr, camp) => {
    // 士
    return new Shi(y, x, type, tr, camp);
  },
  5: (y, x, type, tr, camp) => {
    // 将
    return new Jiang(y, x, type, tr, camp);
  },
  6: (y, x, type, tr, camp) => {
    // 炮
    return new Pao(y, x, type, tr, camp);
  },
  7: (y, x, type, tr, camp) => {
    // 卒
    return new Zu(y, x, type, tr, camp);
  },
};

let typeList = {
  // 下棋顺序枚举
  1: "黑棋",
  2: "红棋",
};
let flag = 0; // 0:未选中棋子，1:选中棋子
let sequence = false; // true:黑棋走，false:红棋走
let ele, x, y;
class Qi {
  // 棋子公共类
  constructor(y, x, type, tr, camp) {
    // 构造器
    this.type = type; // 棋子类型
    this.camp = camp; // 棋子阵营
    this.tr = tr; // 归属tr
    this.td = document.createElement("td");
    this.y = y; // 棋子纵坐标
    this.x = x; // 棋子横坐标
    this.td.dataset.y = y; // 设置标签纵坐标属性
    this.td.dataset.x = x; // 设置标签横坐标属性
    camp == 2 // 设置棋子背景图
      ? this.td.classList.add(`bgc${type + 7}`)
      : this.td.classList.add(`bgc${type}`);
    this.waysArr = []; // 移动坐标方式数组
    tr.appendChild(this.td); // 加入视图
  }
  checked() {
    // 选中棋子
    if (sequence) {
      // 判断黑红下棋顺序
      if (list[y][x].camp == 1) {
        // 黑棋下
        this.getLine(this.x, this.y, 1); // 获取该棋子的走法路线
        this.td.classList.add("checked");
      } else if (list[y][x].camp == 2) {
        alert("黑棋走！");
        clear();
      } else {
        clear();
      }
    } else {
      if (list[y][x].camp == 2) {
        // 红棋下
        this.getLine(this.x, this.y, 1);
        this.td.classList.add("checked");
      } else if (list[y][x].camp == 1) {
        alert("红棋走！");
        clear();
      } else {
        clear();
      }
    }
  }
  down() {
    // 放下棋子
    this.td.classList.remove("checked");
    this.showWays(this.waysArr, 0); // 隐藏走法路线
  }
  filterLine(arr, x, y, isShowRoad) {
    // 筛选后其他棋子后的该棋子的走法路线
    let resultArr = arr
      .flat()
      .filter(
        (item) => item?.type === 0 || (item?.camp && item.camp !== this.camp)
      );
    console.log("过滤掉的走法路线", resultArr);
    return resultArr;
  }
  loopMethod(arr, order, type = 1) {
    // 自定义遍历方法,order控制遍历的顺序
    let resultArr = [];
    if (!arr.length) return resultArr;
    if (order < 0) {
      // 反方向遍历数组
      for (let i = arr.length - 1; i >= 0; i--) {
        if (arr[i].type) {
          // 如果存在路线上有其他棋子的
          if (type == 1) {
            // 车的吃子方法
            if (arr[i].camp != this.camp) resultArr.push(arr[i]);
            break;
          } else {
            // 炮的吃子方法
            for (let j = i - 1; j >= 0; j--) {
              if (arr[j].camp != this.camp && arr[j].type) {
                resultArr.push(arr[j]);
                break;
              }
            }
            break;
          }
        }
        resultArr.push(arr[i]);
      }
    } else {
      for (let i = 0; i < arr.length; i++) {
        if (arr[i].type) {
          // 如果存在路线上有其他棋子的
          if (type == 1) {
            // 车的吃子方法
            if (arr[i].camp != this.camp) {
              // 不同阵营可以吃 并终止添加路线
              resultArr.push(arr[i]);
            } else {
              break;
            }
          } else {
            // 炮的吃子方法
            for (let j = i + 1; j < arr.length; j++) {
              if (arr[j].camp != this.camp && arr[j].type) {
                // 不同阵营 中间有棋子
                resultArr.push(arr[j]);
                break;
              }
            }
            break;
          }
        }
        resultArr.push(arr[i]);
      }
    }
    return resultArr;
  }
  showWays(arr, flag) {
    // 显示棋子可移动到的坐标
    this.waysArr = arr;
    this.waysArr.forEach((item) => {
      flag
        ? item.td.classList.add("showWays")
        : item.td.classList.remove("showWays");
    });
  }

  move(x, y) {
    // 棋子移动
    console.log("开始移动");
    let allowMove = this.waysArr.find((item) => {
      // 判断将要移动的坐标是否在可移动范围内
      return item.x == x && item.y == y;
    });
    if (!allowMove) {
      // 不在可移动范围，就将棋子放下
      return this.down();
    }
    let nextChess = list[y][x]; // 移动到的坐标
    let nextType = nextChess.camp; // 如果坐标上有其他棋子，获取它的阵营
    let y1 = this.td.dataset.y;
    let x1 = this.td.dataset.x;
    let tds = document.getElementsByTagName("td")
    var tdsList = Array.prototype.slice.call(tds)
    list[y1][x1] = menu[0]([y1], [x1], 0, this.tr); // 把原先位置变为空
    list[y][x] = menu[this.type]([y], [x], this.type, this.tr, this.camp); // 新位置赋值
    this.td.dataset.y = y;
    this.td.dataset.x = x;
    // tdsList.forEach(element => {
    //   if(element == this.td ){
    //     this.td.classList.add("filter_td")
    //   }else{
    //     this.td.classList.remove("filter_td")
    //   }
    // });

    this.td.classList.add("filter_td")
    sequence = !sequence; // 交换下棋顺序
    let msg = document.querySelector(".dialog3");
    if (sequence) {
      msg.innerHTML = "黑棋走";
      msg.style.color = "black";
    } else {
      msg.innerHTML = "红棋走";
      msg.style.color = "red";
    }
    let arr = this.getLine(+x, +y, 0); // 计算棋子下一步可移动的坐标,判断是否显示将军
    if (arr.find((item) => item.type == 5 && item.camp !== this.camp)) {
      // 如果棋子下一步的路径包涵将，就显示将军
      this.showMessage(2); // 1：吃 ； 2：将军
    } else if (nextType && nextType !== this.camp) {
      this.showMessage(1); // 1：吃 ； 2：将军
    }
    render();
    if (nextChess.type === 5) {
      // 将军被吃掉,游戏结束
      alert(`游戏结束,${typeList[this.camp]}胜!`);
      list = JSON.parse(JSON.stringify(overlist));
      render();
    }
  }
  showMessage(num) {
    // 吃子和将军的时候给出提示
    if (num == 2) {
      // 将军提示
      console.log("显示将军");
      document.querySelector(".dialog2").style.display = "block";
      setTimeout(() => {
        document.querySelector(".dialog2").style.display = "none";
      }, 1000);
    } else {
      // 吃子提示
      console.log("显示吃");
      document.querySelector(".dialog1").style.display = "block";
      setTimeout(() => {
        document.querySelector(".dialog1").style.display = "none";
      }, 1000);
    }
  }
}


class Ju extends Qi {
  // 车
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }
  getLine(x, y, isShowRoad) {
    // 获取棋子的走法路线，isShowRoad控制是否显示路径
    let lineArr = list.map((item, index) => {
      // 不考虑其他棋子影响下的所有路径
      // 该棋子的纵坐标上移动是否可以走 不能走了就返回本身
      return index === +y ? item : item[x];
    });
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad);
    this.showWays(resultArr, isShowRoad);
    return resultArr;
  }
  filterLine(arr, x, y, isShowRoad) {
    // 筛选移动路径上的棋子
    // 以选中棋子为中心，将x轴和y轴的点分为4份，每一份都要遍历找出满足条件的坐标，最后再合并
    let yArr1 = arr.slice(0, y); // y 正半轴
    let yArr2 = arr.slice(y + 1, arr.length); // y 负半轴
    let xArr1 = arr[y].slice(0, x); // x 负半轴
    let xArr2 = arr[y].slice(x + 1, arr[y].length); // x 正半轴
    console.log({ yArr1, yArr2, xArr1, xArr2 });
    return [
      ...this.loopMethod(xArr1, -1, this.type), // loopMethod：自定义的遍历方法
      ...this.loopMethod(xArr2, 1, this.type),
      ...this.loopMethod(yArr1, -1, this.type),
      ...this.loopMethod(yArr2, 1, this.type),
    ];
  }
}

class Ma extends Qi {
  // 马
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }

  getLine(x, y, isShowRoad) {
    // 获取马可以移动到的所有坐标
    console.log(x, y, "选择棋子的坐标");
    let lineArr = []; // 未筛选的所有可移动的坐标
    if (!list[y][x - 1]?.type) {
      lineArr.push([list[y - 1]?.[x - 2], list[y + 1]?.[x - 2]]);
    }
    if (!list[y][x + 1]?.type) {
      lineArr.push([list[y + 1]?.[x + 2], list[y - 1]?.[x + 2]]);
    }
    if (!list[y - 1]?.[x].type) {
      lineArr.push([list[y - 2]?.[x + 1], list[y - 2]?.[x - 1]]);
    }
    if (!list[y + 1]?.[x].type) {
      lineArr.push([list[y + 2]?.[x + 1], list[y + 2]?.[x - 1]]);
    }
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad); // 棋盘上展示可移动的路径
    return resultArr;
  }
}

class Xiang extends Qi {
  // 象
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }
  getLine(x, y, isShowRoad) {
    // 获取象可以移动到的所有坐标,象心不能有棋子，并且不能过河
    console.log(x, y, "选择棋子的坐标");
    let lineArr = []; // 未筛选的所有可移动的坐标
    if (list[y - 1]?.[x - 1]?.type === 0 && y !== 5) {
      lineArr.push(list[y - 2][x - 2]);
    }
    if (list[y + 1]?.[x + 1]?.type === 0 && y !== 4) {
      lineArr.push(list[y + 2][x + 2]);
    }
    if (list[y - 1]?.[x + 1]?.type === 0 && y !== 5) {
      lineArr.push(list[y - 2][x + 2]);
    }
    if (list[y + 1]?.[x - 1]?.type === 0 && y !== 4) {
      lineArr.push(list[y + 2][x - 2]);
    }
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad); // 棋盘上展示可移动的路径
    return resultArr;
  }
}

class Shi extends Qi {
  // 士
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }
  getLine(x, y, isShowRoad) {
    // 获取士可以移动到的所有坐标
    console.log(x, y, "选择棋子的坐标");
    let lineArr = []; // 未筛选的所有可移动的坐标
    if (x == 3 || x == 5) {
      this.camp == 1 ? lineArr.push(list[1][4]) : lineArr.push(list[8][4]);
    } else {
      this.camp == 1
        ? lineArr.push([list[0][3]], [list[0][5]], [list[2][3]], [list[2][5]])
        : lineArr.push([list[7][3]], [list[7][5]], [list[9][3]], [list[9][5]]);
    }
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad);
    return resultArr;
  }
}

class Jiang extends Qi {
  // 将
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }

  getLine(x, y, isShowRoad) {
    // 获取将可以移动到的所有坐标
    console.log(x, y, "选择棋子的坐标");
    let lineArr = []; // 未筛选的所有可移动的坐标
    lineArr.push(
      [list[y][x + 1]],
      [list[y][x - 1]],
      [list[y - 1]?.[x]],
      [list[y + 1]?.[x]]
    );
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad);
    return resultArr;
  }
  filterLine(arr, x, y, isShowRoad) {
    // 筛选移动路径上的棋子
    // 获取敌方帅的坐标
    let resultArr = arr.filter((item) => {
      // 将有棋子的坐标筛选出来，剩下的就是可以走的地方
      if (this.camp == 1) {
        return (
          item[0]?.x > 2 &&
          item[0]?.x < 6 &&
          item[0]?.y >= 0 &&
          item[0]?.y < 3 &&
          item[0]?.camp != 1
        );
      } else {
        return (
          item[0]?.x > 2 &&
          item[0]?.x < 6 &&
          item[0]?.y >= 7 &&
          item[0]?.y < 10 &&
          item[0]?.camp != 2
        );
      }
    });
    let shuai = list
      .flat()
      .find((item) => item.type === 5 && item.camp !== this.camp); // 敌方帅的坐标
    let jiang = resultArr.flat().find((item) => item.x === shuai.x);
    if (jiang) {
      // 判断将和帅可以走的坐标里面,有没有和对方将为同一列的
      let res = list.flat().find((item) => {
        if (shuai.y > jiang.y) {
          return (
            item.x === jiang.x &&
            item.y > jiang.y &&
            item.y < shuai.y &&
            item.type
          );
        } else {
          return (
            item.x === jiang.x &&
            item.y < jiang.y &&
            item.y > shuai.y &&
            item.type
          );
        }
      });
      if (!res) {
        // 如果两个帅在同一列,并且中间没有棋子,就不可以走,把这个坐标删除
        let resArr = resultArr
          .flat()
          .filter((item) => !(item.x == jiang.x && item.y == jiang.y));
        return resArr;
      }
    }
    return resultArr.flat();
  }
}

class Pao extends Qi {
  // 炮
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }

  getLine(x, y, isShowRoad) {
    // 获取炮棋子可以移动到的所有坐标
    console.log(x, y, "选择棋子的坐标");
    let lineArr = list.map((item, index) => {
      // 未筛选的所有可移动的坐标
      return index === +y ? item : item[x];
    });
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad);
    return resultArr;
  }
  filterLine(arr, x, y, isShowRoad) {
    // 筛选移动路径上的棋子
    let yArr1 = arr.slice(0, y);
    let yArr2 = arr.slice(y + 1, arr.length);
    let xArr1 = arr[y].slice(0, x);
    let xArr2 = arr[y].slice(x + 1, arr[y].length);
    console.log({ yArr1, yArr2, xArr1, xArr2 });
    return [
      ...this.loopMethod(xArr1, -1, this.type),
      ...this.loopMethod(xArr2, 1, this.type),
      ...this.loopMethod(yArr1, -1, this.type),
      ...this.loopMethod(yArr2, 1, this.type),
    ];
  }
}

class Zu extends Qi {
  // 卒
  constructor(y, x, type, tr, camp) {
    super(y, x, type, tr, camp);
  }

  getLine(x, y, isShowRoad) {
    // 获取卒可以移动到的所有坐标
    console.log(x, y, "选择棋子的坐标");
    let lineArr = []; // 未筛选的所有可移动的坐标
    if ((this.camp == 1 && y < 5) || (this.camp == 2 && y > 4)) {
      // 过河前的移动路径
      this.camp == 1
        ? lineArr.push(list[y + 1]?.[x])
        : lineArr.push(list[y - 1]?.[x]);
    } else {
      // 过河后的移动路径
      if (this.camp == 1) {
        lineArr.push([list[y + 1]?.[x], list[y][x + 1], list[y][x - 1]]);
      } else {
        lineArr.push([list[y - 1]?.[x], list[y][x + 1], list[y][x - 1]]);
      }
    }
    let resultArr = this.filterLine(lineArr, x, y, isShowRoad); // 将路径上有棋子的坐标筛选出来
    this.showWays(resultArr, 1, isShowRoad);
    return resultArr;
  }
}

//封装渲染函数
const render = () => {
  document.querySelector("table").innerHTML = "";
  list.forEach((item, y) => {
    let tr = document.createElement("tr");
    item.forEach((item2, x) => {
      let type = list[y][x].type;
      //   参数：行、列、类型、dom、阵营
      list[y][x] = menu[type](y, x, item2.type, tr, item2.camp); // 枚举生成对应的棋子对象
    });
    document.querySelector("table").appendChild(tr);
  });
};
render();

function clear() {
  // 清空数据
  flag = 0;
  x = null;
  y = null;
}
document.querySelector("table").addEventListener("click", (e) => {
  // 棋子的点击事件
  // if (x == e.target.dataset.x && y == e.target.dataset.y) {
  //   // 两次点击的地方一样，就放下棋子
  //   clear(); // 清空数据
  //   ele.down(); // 放下棋子
  //   return;
  // }
  socket.emit("play", {
    x: e.target.dataset.x,
    y: e.target.dataset.y,
  })
  // if (list[y][x].type && !flag) {
  //   // 选中要移动的棋 flag = 0 #### !0 = true 做判断
  //   ele = list[y][x];
  //   console.log(ele, "选择的棋子", !flag);
  //   flag = 1;

  //   ele.checked();

  // } else if (flag) {
  //   // 移动棋子 1 = true 做判断
  //   ele.move(x, y);

  //   clear(); // 清空数据
  // } else {
  //   console.log("此处没有棋子!");
  //   clear(); // 清空数据
  // }
});

socket.on("play", (data) => {
  // 下棋
  if (x == data.x && y == data.y) {
    // 两次点击的地方一样，就放下棋子
    clear(); // 清空数据
    ele.down(); // 放下棋子
    return;
  }
  x = data.x || x;
  y = data.y || y;
  if (list[y][x].type && !flag) {
    // 选中要移动的棋 flag = 0 #### !0 = true 做判断
    ele = list[y][x];
    console.log(ele, "选择的棋子", !flag);
    flag = 1;
    ele.checked();

  } else if (flag) {
    // 移动棋子 1 = true 做判断
    ele.move(x, y);
    clear(); // 清空数据
  } else {
    console.log("此处没有棋子!");
    clear(); // 清空数据
  }
});

